package aspectos;

import java.util.ArrayList;
import java.util.List;

import adicionales.ContadorPorObjeto;
import adicionales.Tupla;
import annotations.Monitored;
							
public aspect ContadorLlamadasAspect{
	
	private List<ContadorPorObjeto> contadores = new ArrayList<ContadorPorObjeto>();
	
	pointcut monitoringCatch(Object target):
	call(@Monitored * *(..))&& target(target);
	
	before(Object target):monitoringCatch(target){
		actualizarUnContador(target, thisJoinPoint.getSignature().getName());
	}
	
	public int cantLlamadas(Object p1, String st){
		if(this.objetos().contains(p1)){
			return this.cantLlamadasAux(p1, st);
		}else{
			return 0;
		}
	}
	
	protected ArrayList<Object> objetos(){
		
		ArrayList<Object> objs = new ArrayList<Object>();
		for(ContadorPorObjeto each: this.contadores){
			objs.add(each.getObject());
		}
		return objs;
	}
	
	protected int cantLlamadasAux(Object p1,String source){
		return this.buscarContador(p1).cantLlamadas(source);
	}
	
	protected void actualizarUnContador(Object o, String source){
		
		if(this.objetos().contains(o)){
			this.buscarContador(o).agregarMetodo(source);
		} else{
			ContadorPorObjeto cpo = new ContadorPorObjeto(o);
			Tupla tupla = new Tupla(source,1);
			cpo.getTuplas().add(tupla);
			this.contadores.add(cpo);
		}
	}
	
	protected ContadorPorObjeto buscarContador(Object o){
		
		ContadorPorObjeto cpo = new ContadorPorObjeto();
		
		for(ContadorPorObjeto each : this.contadores){
			if(each.getObject().equals(o)){
				cpo = each;
			}
		}
		return cpo;
	}
	
}
